<template>
  <el-dialog
    :title="title"
    :model-value="visible"
    width="720px"
    append-to-body
    @close="onCancel"
    class="add-dlg"
  >
    <div class="add-grid">
      <!-- 行 1：选择文件 / 文件夹 -->
      <div class="row-pickers">
        <el-upload
          :auto-upload="false"
          :show-file-list="false"
          :multiple="multiple"
          :accept="accept"
          :on-change="onUploadChange"
          :disabled="uploading"
        >
          <el-button type="primary" size="small" :loading="uploading">
            <el-icon><UploadFilled /></el-icon>
            选择文件
          </el-button>
        </el-upload>

        <el-button
          size="small"
          :disabled="uploading"
          v-if="directory"
          @click="pickDirectory"
        >
          <el-icon><FolderOpened /></el-icon>
          选择文件夹
        </el-button>

        <input
          ref="dirPickerRef"
          class="dir-input"
          type="file"
          webkitdirectory
          directory
          multiple
          @change="onDirectoryPicked"
        />
      </div>

      <!-- 直接紧贴在“选择文件”下方的文件列表 -->
      <div class="row-list">
        <template v-if="files.length">
          <el-scrollbar max-height="220" class="picked-list card">
            <div v-for="(f,i) in files" :key="i" class="picked-row">
              <div class="file-main">
                <span class="file-name" :title="f.raw?.name || '-'">{{ f.raw?.name || '-' }}</span>
                <span class="file-path" :title="f.relativePath || '-'">{{ f.relativePath || '-' }}</span>
              </div>
              <div class="file-meta">
                <span class="muted">{{ (f.raw?.size ?? 0) / 1024 / 1024 | toMB }} MB</span>
              </div>
            </div>
          </el-scrollbar>
          <div class="picked-actions">
            <el-tag size="small" type="success" effect="light">已选 {{ files.length }} 个</el-tag>
            <el-button link type="danger" @click="clearFiles">清空</el-button>
          </div>
        </template>
        <el-empty v-else description="还没有选择文件" class="empty card" />
      </div>

      <!-- 行 2：文件类型（单独一行） + 备注（限制宽度） -->
      <div class="row-meta card">
        <el-form label-width="64px" class="meta-form">
          <el-form-item label="类型">
            <el-select
              v-model="meta.bizTag"
              placeholder="请选择文件类型"
              size="small"
              class="type-select"
              :disabled="uploading"
              clearable
            >
              <el-option
                v-for="opt in typeOptions"
                :key="opt.value"
                :label="opt.label"
                :value="opt.value"
              />
            </el-select>
          </el-form-item>

          <el-form-item label="备注" v-if="showRemark">
            <el-input
              v-model="meta.remark"
              placeholder="备注（可选）"
              class="remark-input"
            />
          </el-form-item>
        </el-form>
      </div>
    </div>

    <template #footer>
      <div class="dialog-footer pretty-footer">
        <el-button :disabled="uploading" @click="onCancel">取 消</el-button>
        <el-button type="primary" :loading="uploading" @click="submit">确 定</el-button>
      </div>
    </template>
  </el-dialog>
</template>


  
  <script setup>
  import { ref, reactive, computed, getCurrentInstance, watch, nextTick } from 'vue'
  import { UploadFilled, FolderOpened } from '@element-plus/icons-vue'
  import { ElMessage } from 'element-plus'

  // script 里 
  
  const props = defineProps({
    /** v-model */
    modelValue: { type: Boolean, default: false },
    /** 必传：上传函数 uploadFn(FormData) */
    uploadFn: { type: Function, required: true },
  
    /** 可选项 */
    title: { type: String, default: '新增文件' },
    accept: { type: String, default: '.png,.jpg,.jpeg,.webp,.gif,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.zip,.rar' }, 
    maxSizeMB: { type: Number, default: 500 },
    multiple: { type: Boolean, default: true },
    directory: { type: Boolean, default: true },
    showRemark: { type: Boolean, default: true },
    bizTag: String,
    /** 文件类型下拉选项 */
    typeOptions: {
      type: Array,
      default: () => ([
        { label: '通用',  value: 'general' },
        { label: '图片',  value: 'image' },
        { label: '文档',  value: 'doc' },
        { label: '表格',  value: 'sheet' },
        { label: '合同',  value: 'contract' },
      ])
    }
  })
  
  const emit = defineEmits(['update:modelValue', 'update:bizTag', 'success', 'error', 'cancel'])
  /** v-model 可控 */
  const visible = computed({
    get: () => props.modelValue,
    set: (v) => emit('update:modelValue', v)
  })
  
  /** 选择的文件 */
  const files = ref([]) // { raw: File, relativePath: string }[]
  /** 额外元数据 */
  const meta = reactive({
    bizTag: '',
    remark: ''
  })
  /** 状态 */
  const uploading = ref(false)
  /** 目录 input */
  const dirPickerRef = ref(null)
  
  const noop = () => {}
  
  function beforeOne(file) {
    const ok = file.size / 1024  < props.maxSizeMB
    console.log(ok);
    if (!ok) {
      ElMessage.error(`文件 ${file.name} 超过 ${props.maxSizeMB}MB`)
    }
    return ok
  }
  
  /** 选择文件 */

  // 工具：按大小分组
function splitBySize(list, limitMB) {
  const valid = [], over = []
  for (const it of list) {
    const sz = (it.raw?.size ?? 0) / 1024 / 1024
    if (sz > limitMB) over.push(it)
    else valid.push(it)
  }
  return { valid, over }
}

// 选择文件
async function onUploadChange(_u, uploadFiles) {
  const picked = (uploadFiles || []).map(f => ({
    raw: f.raw || f,
    relativePath: f.relativePath || f.raw?.webkitRelativePath || ''
  }))
  const { valid, over } = splitBySize(picked, props.maxSizeMB)
  if (over.length) emit('oversize', { over: over.map(x => x.raw), limitMB: props.maxSizeMB })
  files.value = valid
}

// 选择文件夹
async function onDirectoryPicked(e) {
  const picked = Array.from(e.target.files || []).map(raw => ({
    raw,
    relativePath: raw.webkitRelativePath || ''
  }))
  const { valid, over } = splitBySize(picked, props.maxSizeMB)
  if (over.length) emit('oversize', { over: over.map(x => x.raw), limitMB: props.maxSizeMB })
  files.value = valid
  e.target.value = '' // 重置
} 

  function pickDirectory() {
    dirPickerRef.value?.click()
  } 
  /** 清空选择 */
  function clearFiles() {
    files.value = []
  }
  
  /** 对外暴露：open/close（可选，父组件也可以用 v-model 控制） */
  function open() { visible.value = true }
  function close() { visible.value = false }
  defineExpose({ open, close, clearFiles })
  
  /** 取消 */
  function onCancel() {
    visible.value = false
    emit('cancel')
  }
  
  /** 提交上传 */
  async function submit() {
    if (!files.value.length) return ElMessage.warning('请先选择文件或文件夹')
    if (!meta.bizTag)        return ElMessage.warning('请选择文件类型')
  
    const fd = new FormData()
    let count = 0
    for (const f of files.value) {
        console.log(f);
      if (!f?.raw) continue
      if (!beforeOne(f.raw)) continue
      fd.append('files', f.raw)
      fd.append('relativePaths', f.relativePath || '')
      count++
    }
    if (!count) return
  
    fd.append('bizTag', meta.bizTag)
    if (meta.remark) fd.append('remark', meta.remark)
  
    uploading.value = true
    try {
      await props.uploadFn(fd)
      ElMessage.success(`上传成功：${count} 个`)
      emit('success', { count, bizTag: meta.bizTag })
      // 关闭并重置
      visible.value = false
      files.value = []
      meta.remark = ''
      // 保留 bizTag 选择习惯，如不需要可清空：meta.bizTag = ''
    } catch (e) {
      ElMessage.error('上传失败')
      emit('error', e)
    } finally {
      uploading.value = false
    }
  }

  watch(() => props.bizTag, v => { meta.bizTag = v })
  watch(() => meta.bizTag, v => emit('update:bizTag', v))

  onMounted(()=>console.log('[AddDlg] max=', props.maxSizeMB, 'accept=', props.accept))

  </script>
  
  <style scoped>
:root{
  --card-bg:#fff;
  --card-bd:#e5e7eb;
  --muted:#909399;
  --radius:12px;
  --radius-sm:8px;
}
@media (prefers-color-scheme: dark){
  :root{
    --card-bg:#1e1f24;
    --card-bd:#2a2c33;
    --muted:#b5b7c0;
  }
}

.add-dlg :deep(.el-dialog__header){
  padding:14px 18px 8px;
  border-bottom:1px solid var(--card-bd);
}
.add-dlg :deep(.el-dialog__body){
  padding:16px;
}
.add-dlg :deep(.el-dialog__footer){
  padding:10px 16px 14px;
  border-top:1px solid var(--card-bd);
}

.add-grid{
  display:grid;
  gap:12px;
}

/* 行 1：选择文件 */
.row-pickers{
  display:flex;
  align-items:center;
  gap:10px;
  flex-wrap:wrap;
}

/* 紧跟其下的列表区域 */
.row-list{
  display:flex;
  flex-direction:column;
  gap:8px;
}

/* 行 2：类型 + 备注（同一行，自适应；小屏自动换行） */
.row-meta{
  padding:12px;
}
.meta-form{
  display:flex;
  align-items:flex-start;
  flex-wrap:wrap;
  gap:12px 24px;
}
.type-select{
  width:220px;
}

/* 限制备注文本框宽度（在可用空间内最大 420px） */
.remark-input{
  max-width:420px;
  width:100%;
}
.remark-input :deep(.el-input__wrapper){
  border-radius: var(--radius-sm);
}

/* 卡片通用 */
.card{
  background:var(--card-bg);
  border:1px solid var(--card-bd);
  border-radius:var(--radius);
  padding:8px;
}

/* 列表样式（更紧凑，贴近按钮） */
.picked-list{
  padding:6px;
  border-radius:var(--radius);
}
.picked-row{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:12px;
  padding:8px 10px;
  border-radius:var(--radius-sm);
}
.picked-row:hover{
  background-color:rgba(0,0,0,0.035);
}
@media (prefers-color-scheme: dark){
  .picked-row:hover{ background-color:rgba(255,255,255,0.06); }
}

/* 文件名与路径 */
.file-main{
  min-width:0;
  display:flex;
  flex-direction:column;
  gap:2px;
}
.file-name{
  font-size:13px;
  font-weight:600;
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
.file-path{
  font-size:12px;
  color:var(--muted);
  white-space:nowrap;
  overflow:hidden;
  text-overflow:ellipsis;
}
.file-meta{ font-size:12px; color:var(--muted); }

/* 列表下的小动作区（数量 + 清空） */
.picked-actions{
  display:flex;
  align-items:center;
  gap:8px;
  padding:0 2px;
}

/* 输入/滚动条细节 */
:deep(.el-input__wrapper){ border-radius:8px; }
.picked-list :deep(.el-scrollbar__bar.is-vertical){ width:6px; }
.picked-list :deep(.el-scrollbar__thumb){ border-radius:6px; }

/* 隐藏真实目录 input */
.dir-input{
  position:absolute;
  width:0;height:0;opacity:0;pointer-events:none;
}

.pretty-footer{
  display:flex;justify-content:flex-end;gap:8px;
}
.muted{ color:var(--muted); }
.empty{ padding:18px; }
</style>

  
  